#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include <time.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include "os_api.h"
#include "ps_api.h"
#include "dev_api.h"
#include "debug.h"
#include "sockets.h"
#include "def.h"
#include "netdb.h"

#define _TASK_STACK_SIZE    (1024*2)

static void* _task_stack = NULL;

static OSTaskRef _task_ref = NULL;


int connect_service_tcp(char * ip, int port)
{
	int client_socket = -1;
	struct sockaddr_in client_addr;  
    struct hostent * host_entry = NULL;
    
	if ((host_entry = gethostbyname(ip)) == NULL)
	{
        LOG_PRINTF("dns parse error!\n");
		return client_socket ;
	}
    memset(&client_addr, 0,sizeof(client_addr));  
    client_addr.sin_family = AF_INET; 
	client_addr.sin_port   = htons(port);
	client_addr.sin_addr   =  * (struct in_addr *) host_entry->h_addr_list[0];
	
	client_socket = socket(AF_INET, SOCK_STREAM, 0);  
	
    if (client_socket < 0)  {  
        LOG_PRINTF("create socket failed!\n");  
        return client_socket; 
    }  	

    socklen_t server_addr_length = sizeof(client_addr);  
    if (connect(client_socket, (struct sockaddr*)&client_addr, server_addr_length) < 0) {  
        LOG_PRINTF("can not connect to %s:%d\n", ip, port);  
        return -1; 
    } 

	return client_socket;
}

int connect_service_tcp2(char *addr, char *portStr)
{
    int ret;
	int client_socket = -1;
    struct addrinfo hints;
    struct addrinfo *result, *rp;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = 0;
    hints.ai_protocol = 0;
    ret = getaddrinfo(addr, portStr, &hints, &result);
    if (ret != 0) {
        LOG_PRINTF("connect_service_tcp2: resolve error\n");
        return -1;
    }

    for (rp = result; rp; rp = rp->ai_next) {
        client_socket = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (client_socket < 0) {
            LOG_PRINTF("connect_service_tcp2: socket error\n");
            continue;
        }

        ret = connect(client_socket, rp->ai_addr, rp->ai_addrlen);
        if (ret < 0) {
            LOG_PRINTF("connect_service_tcp2: connect error\n");
            close(client_socket);
            client_socket = -1;
            continue;
        } else {
            break;
        }
    }

	return client_socket;
}

static void _testsocket(void)
{
    int ret, sock = -1;
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    char buf[128];

    LOG_PRINTF("_testsocket\n");

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = 0;
    hints.ai_protocol = 0;
	fd_set master, read_fds;
	int i,fdmax;
	fdmax = 64;
	
	//sock = connect_service_tcp("203.156.205.55",9999);
    //sock = connect_service_tcp2("test.51modem.com", "3355");
	sock = connect_service_tcp2("222.66.94.47", "15999");
	
    if (sock < 0) {
        LOG_PRINTF("_testsocket: connect error\n");
        return;
    }

    ret = send(sock, "abcdefg", 7, 0);
    if (ret != 7) {
        LOG_PRINTF("_testsocket: send error\n");
        close(sock);
        return;
    }
	FD_ZERO(&master);
	FD_ZERO(&read_fds);
	FD_SET(sock, &master);
	read_fds = master;

	if(select(fdmax, &read_fds, NULL, NULL, NULL) == -1) {
		LOG_PRINTF("%s[%d], select error %d\n", __FUNCTION__, 0, lwip_getsockerrno(sock));
        close(sock);
        return;
	}
    ret = recv(sock, buf, sizeof(buf) - 1, 0);
    if (ret <= 0) {
        LOG_PRINTF("_testsocket: recv error: %d\n", ret);
        close(sock);
        return;
    }
    buf[ret] = '\0';
    LOG_PRINTF("_testsocket: data: %s\n", buf);
    close(sock);

}

void wait_network_ready(void)
{
    int count = 30;
    while(count-- && ps_GetNetworkReady() == FALSE){	
        OSATaskSleep(200);
    }

    if (count <= 0){
        LOG_PRINTF("dev_CtrlReset.\n");
        // 判定如果处于生产模式时（需要写号校准），不要重启模块，主要针对提供固件给原厂生产的场景，重启会影响生产
        if (dev_IsProductionMode()){
            dev_CtrlReset(0);
        }

    }
}

static void _task(void *ptr)
{
    wait_network_ready();

    _testsocket();
}



int main(void)
{
    int ret;

    _task_stack = malloc(_TASK_STACK_SIZE);
    ASSERT(_task_stack != NULL);

    ret = OSATaskCreate(&_task_ref, _task_stack, _TASK_STACK_SIZE, 85, "test-task", _task, NULL);
    ASSERT(ret == OS_SUCCESS);
    
    return 0;
}